//
//  NMGradientNode.swift
//  NetEaseMusic
//
//  Created by SAGESSE on 2020/3/1.
//  Copyright © 2020 SAGESSE. All rights reserved.
//

import UIKit
import AsyncDisplayKit


class NMGradientNode: ASDisplayNode {
    
    override init() {
        super.init()
        
        self.isOpaque = false
        self.isUserInteractionEnabled = false
        self.needsDisplayOnBoundsChange = true
    }
    
    var colors: [UIColor]? {
        didSet {
            setNeedsDisplay()
        }
    }
    
    var startPoint: CGPoint = .init(x: 0.5, y: 0.0) {
        didSet {
            setNeedsDisplay()
        }
    }
    var endPonit: CGPoint = .init(x: 0.5, y: 1.0) {
        didSet {
            setNeedsDisplay()
        }
    }
    
    override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
        return DrawParameter(self)
    }

  
    override class func display(withParameters parameters: Any?, isCancelled isCancelledBlock: () -> Bool) -> UIImage? {
        guard let parameters = parameters as? DrawParameter else {
            return nil
        }
        
        guard let gradient = CGGradient(colorsSpace: nil, colors: parameters.colors as CFArray, locations: nil) else {
            return nil
        }

        return ASGraphicsCreateImageWithTraitCollectionAndOptions(parameters.trait, parameters.bounds.size, parameters.isOpaque, parameters.contentScale, nil) {
            guard let context = UIGraphicsGetCurrentContext() else {
                return
            }
            context.saveGState()
            
            // Apply corner.
            if parameters.cornerRadius > 0 {
                let path = UIBezierPath(roundedRect: context.boundingBoxOfClipPath, byRoundingCorners: [.topLeft, .topRight], cornerRadii: .init(width: parameters.cornerRadius, height: parameters.cornerRadius))
                path.addClip()
            }
            
            // Draw gradient.
            context.drawLinearGradient(gradient, start: parameters.start, end: parameters.end, options: .drawsBeforeStartLocation)
            context.restoreGState()
        }
    }
    
//    override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
//        let spec = ASStackLayoutSpec.horizontal()
//
//        spec.children = subnodes
//        spec.spacing = 4
//        spec.justifyContent = .spaceBetween
//
//        return ASInsetLayoutSpec(insets: margins, child: spec)
//    }
    
    private class DrawParameter: NSObject {
        
        var colors: [CGColor]
        
        var start: CGPoint
        var end: CGPoint
        
        var trait: ASPrimitiveTraitCollection
        
        var bounds: CGRect
        var isOpaque: Bool
        var contentScale: CGFloat
        
        var backgroundColor: UIColor?
        
        var cornerRadius: CGFloat
        var maskedCorners: UIRectCorner

        
        init?(_ node: NMGradientNode) {
            self.colors = node.colors?.map { $0.cgColor } ?? []
            guard !self.colors.isEmpty else {
                return nil
            }
            self.start = .init(x: node.startPoint.x * node.bounds.width, y: node.startPoint.y * node.bounds.height)
            self.end = .init(x: node.endPonit.x * node.bounds.width, y: node.endPonit.y * node.bounds.height)
            guard self.start != self.end else {
                return nil
            }
            self.trait = node.primitiveTraitCollection()
            self.bounds = node.bounds
            self.isOpaque = node.isOpaque
            self.contentScale = node.contentsScaleForDisplay
            self.backgroundColor = node.backgroundColor
            self.cornerRadius = node.cornerRadius
            self.maskedCorners = []
            
            if node.maskedCorners.contains(.layerMinXMinYCorner) {
                self.maskedCorners.formIntersection(.topLeft)
            }
            if node.maskedCorners.contains(.layerMinXMaxYCorner) {
                self.maskedCorners.formIntersection(.bottomLeft)
            }
            if node.maskedCorners.contains(.layerMaxXMinYCorner) {
                self.maskedCorners.formIntersection(.topRight)
            }
            if node.maskedCorners.contains(.layerMaxXMaxYCorner) {
                self.maskedCorners.formIntersection(.bottomRight)
            }
            
            super.init()
        }
        
    }
}
